#include "SystemServer.h"
#include "Util/util.h"
#include "Protocol/ProtocolApi.h"
#include "HttpCmdProcess.h"

using namespace Protocol;
SystemServer *SystemServer::s_systemServer = nullptr;

using namespace Fdt;

int DEV_GetDevPower(void)
{
	return 0;
}
int DEV_SetLiveFlag(int flag)
{
	return 0;
}
int DEV_CheckDevPasswd(const char *passwd)
{
	return 0;
}
int DEV_GetUvcStatus(void)
{
	return 0;
}

char* DEV_GetDevVersion(void)
{
	return "NULL";
}
char* DEV_GetDevName(void)
{
	return "NULL";
}
int DEV_GetPlayFlag(void)
{
	return 0;
}
int MediaCommonSaveTimeZoneOffset(float TimeZoneOffset)
{
	return 0;
}
int MEDIA_AudioUacConnected(void)
{
	return 0;
}
int MEDIA_AudioLineIn(void)
{
	return 0;
}
char* DEV_GetDevMac(char* devMac)
{
	return "NULL";
}

void SystemServerInit()
{
	SystemServer::instance();
}

SystemServer::SystemServer(){
	RegistRPC();
}

void SystemServer::RegistRPC(){

	RPCMethodMap method_map;
	method_map.emplace("SetTime", CRPCFuntion::CreateRpc([this](const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){
		return SetTime(request, inMap, response, outMap);
	}));

	method_map.emplace("SetTimeMs", CRPCFuntion::CreateRpc([this](const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){
		return SetTimeMs(request, inMap, response, outMap);
	}));

	method_map.emplace("GetTime", CRPCFuntion::CreateRpc([this](const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){
		return GetTime(request, inMap, response, outMap);
	}));

	method_map.emplace("GetPower", CRPCFuntion::CreateRpc([this](const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){
		return GetPower(request, inMap, response, outMap);
	}));

	method_map.emplace("SetLive", CRPCFuntion::CreateRpc([this](const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){
		return SetLive(request, inMap, response, outMap);
	}));

	method_map.emplace("CheckPasswd", CRPCFuntion::CreateRpc([this](const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){
		return CheckPasswd(request, inMap, response, outMap);
	}));

	method_map.emplace("GetUvcStatus", CRPCFuntion::CreateRpc([this](const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){
		return GetUvcStatus(request, inMap, response, outMap);
	}));

	method_map.emplace("GetDevInfo", CRPCFuntion::CreateRpc([this](const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){
		return GetDevInfo(request, inMap, response, outMap);
	}));

	method_map.emplace("GetAudioIn", CRPCFuntion::CreateRpc([this](const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){
		return GetAudioIn(request, inMap, response, outMap);
	}));
	
	method_map.emplace("GetDeviceList", CRPCFuntion::CreateRpc([this](const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){
		return GetDeviceList(request, inMap, response, outMap);
	}));

	method_map.emplace("Subscribe", CRPCFuntion::CreateRpc([this](const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){
		return Subscribe(request, inMap, response, outMap);
	}));

	IProtocolInterface::GetInstance()->RegistProtocol("System", method_map);
}



bool SystemServer::GetTime(const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){

	uint64_t Time = getCurrentMillisecond(1);
	response["data"]["Param"]["Time"] = Time;
	response["data"]["Param"]["Result"] = true;
	tracef("===============================");
	return true;
}

bool SystemServer::SetTimeMs(const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){

	uint64_t Time;
	if(!Json::getJsonUInt64(request, "Param.Time", Time)){
		response["data"]["Param"]["Result"] = false;
		return false;
	}
	
	float TimeZoneOffset;
	if(!Json::getJsonFloat(request, "Param.TimeZoneOffset", TimeZoneOffset)){
		response["data"]["Param"]["Result"] = false;
		return false;
	}

	if ((TimeZoneOffset < -12) || (TimeZoneOffset > 12))
	{
		printf("TimeZoneOffset error %f\n",TimeZoneOffset);
	}

	MediaCommonSaveTimeZoneOffset(TimeZoneOffset);
	std::string TimeZoneAbbr;
	Json::getJsonString(request, "Param.TimeZoneAbbr", TimeZoneAbbr);

	std::string TimeZoneId;
	Json::getJsonString(request, "Param.TimeZoneId", TimeZoneId);

	tracef("Time %llu TimeZoneOffset %f TimeZoneAbbr %s TimeZoneId %s\n",Time, TimeZoneOffset, TimeZoneAbbr.c_str(), TimeZoneId.c_str());
	setSystemTimeMs(Time);
	system("hwclock -w");
	uint64_t localtime = getCurrentMillisecond(1);
	printf("localtime = %llu\n",localtime);
	response["data"]["Param"]["Time"] = localtime;
	response["data"]["Param"]["TimeZoneOffset"] = TimeZoneOffset;

	response["data"]["Param"]["Result"] = true;
	return true;
}

bool SystemServer::SetTime(const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){
	std::string timeType;
	if(!Json::getJsonString(request, "Param.Type", timeType)){
		response["data"]["Param"]["Result"] = false;
		return false;
	}

	//%Y-%m-%d %H:%M:%S
	//2022/10/28 16:40:00
	//	std::string test = getTimeStr("%a,%d %b %Y %T %Z", 0);
	//	tracef("test--------->%s", test.c_str());
	if(timeType == "RFC3339"){
		std::string format;
		if(!Json::getJsonString(request, "Param.Format", format)){
			response["data"]["Param"]["Result"] = false;
			return false;
		}
		std::string time_string;
		if(!Json::getJsonString(request, "Param.Time", time_string)){
			response["data"]["Param"]["Result"] = false;
			return false;
		}

		setSystemTime(format, time_string);
	}
	else if(timeType == "RFC2822") {
		std::string format;
		if(!Json::getJsonString(request, "Param.Format", format)){
			response["data"]["Param"]["Result"] = false;
			return false;
		}
		std::string time_string;
		if(!Json::getJsonString(request, "Param.Time", time_string)){
			response["data"]["Param"]["Result"] = false;
			return false;
		}

		setSystemTime(format, time_string);
	}
	else{
		response["data"]["Param"]["Result"] = false;
		return false;
	}

	system("hwclock -w");
	response["data"]["Param"]["Result"] = true;
	return true;
}

bool SystemServer::GetPower(const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){

	response["data"]["Param"]["Power"] = DEV_GetDevPower();
	response["data"]["Param"]["Result"] = true;
	return true;
}

bool SystemServer::SetLive(const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){
	bool enable;
	if(!Json::getJsonBool(request, "Param.Enable", enable)){
		response["data"]["Param"]["Result"] = false;
		return false;
	}
	DEV_SetLiveFlag(enable);
	response["data"]["Param"]["Result"] = true;
	return true;
}

bool SystemServer::CheckPasswd(const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){
	std::string keys;
	if(!Json::getJsonString(request, "Param.Keys", keys)){
		response["data"]["Param"]["Result"] = false;
		return false;
	}
	if (DEV_CheckDevPasswd(keys.c_str()))
	{
		response["data"]["Param"]["Result"] = true;
	}
	else
	{
		response["data"]["Param"]["Result"] = false;
	}

	return true;
}

bool SystemServer::GetUvcStatus(const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){
	
	if (DEV_GetUvcStatus())
	{
		response["data"]["Param"]["Enable"] = true;
	}
	else
	{
		response["data"]["Param"]["Enable"] = false;
	}

	return true;
}

bool SystemServer::GetDevInfo(const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){

	response["data"]["Param"]["Power"] = DEV_GetDevPower();
	if (DEV_GetUvcStatus())
	{
		response["data"]["Param"]["UvcEnable"] = true;
	}
	else
	{
		response["data"]["Param"]["UvcEnable"] = false;
	}

	if (DEV_GetPlayFlag())
	{
		response["data"]["Param"]["Busy"] = "yes";
	}
	else
	{
		response["data"]["Param"]["Busy"] = "no";
	}
	char devMac[32] = {0};
	response["data"]["Param"]["Version"] = DEV_GetDevVersion();
	response["data"]["Param"]["DevName"] = DEV_GetDevName();
	response["data"]["Param"]["Mac"] = DEV_GetDevMac(devMac);
	response["data"]["Param"]["Result"] = true;
	return true;
}

bool SystemServer::GetAudioIn(const Json::Value &request, const BufferMap::Ptr &inMap, Json::Value &response, BufferMap::Ptr &outMap){

	response["data"]["Param"]["LineIn"] = MEDIA_AudioLineIn();
	response["data"]["Param"]["UacConnected"] = MEDIA_AudioUacConnected();
	response["data"]["Param"]["Result"] = true;
	return true;
}


bool SystemServer::GetDeviceList(const Json::Value &request, const Fdt::BufferMap::Ptr &inMap, Json::Value &response, Fdt::BufferMap::Ptr &outMap){
	Json::Value table;
	if(Media::HttpCmdProcess::instance()->GetDeviceList(table)){
		response["data"]["Param"]["DeviceList"] = table;
	}else{
		return false;
	}
	return true;
}

bool SystemServer::Subscribe(const Json::Value &request, const Fdt::BufferMap::Ptr &inMap, Json::Value &response, Fdt::BufferMap::Ptr &outMap){
	auto lam = [](Json::Value newTable){
		Json::Value notifyReq;
		notifyReq["notify"]["Class"] = "System";
		notifyReq["notify"]["Method"] = "Subscribe";
		notifyReq["notify"]["Param"]["Name"] = "GetDeviceList";
		notifyReq["notify"]["Param"]["DeviceList"] = newTable;

		// tracef("notify json -> %s\n", notifyReq.toStyledString().c_str());
		IProtocolInterface::GetInstance()->SendWebsocketReq(notifyReq);
		return true;
	};
	return Media::HttpCmdProcess::instance()->Subscribe(lam);
}